#include "pch.hpp"
#include "Font.hpp"




AdvancedFont::AdvancedFont(QString fileName)
	: AdvancedGlyph(textureFileName(openFile(fileName), fileName))
	, m_fileName(fileName)
{
	QString data = openFile(fileName);

	// Basically everything is found through regular expressions
	// Its much code, but structured, simply read to understand...

	QRegExp rx("face=\\\"([^\\\"]*)\\\"");
	if(rx.indexIn(data) != -1)
		m_desc.name = m_name = rx.cap(1);
	else
		BOOSTEXT_THROW(exception("Missing font-face description"));

	rx = QRegExp("size=([\\d]+)");
	if(rx.indexIn(data) != -1)
		m_desc.size = rx.cap(1).toUInt();
	else
		BOOSTEXT_THROW(exception("Missing font-size description"));

	rx = QRegExp("bold=(\\d)");
	if(rx.indexIn(data) != -1)
		m_desc.bold = rx.cap(1) == "1";
	else
		BOOSTEXT_THROW(exception("Missing font-boldness description"));

	rx = QRegExp("italic=(\\d)");
	if(rx.indexIn(data) != -1)
		m_desc.italic = rx.cap(1) == "1";
	else
		BOOSTEXT_THROW(exception("Missing font-italic description"));

	rx = QRegExp("outline=(\\d)");
	if(rx.indexIn(data) != -1)
		m_desc.outline = rx.cap(1).toUInt();
	else
		BOOSTEXT_THROW(exception("Missing font-outline description"));

	/*rx = QRegExp("charset=\\\"([^\\\"]+)\\\"");
	if(rx.indexIn(data) != -1)
	{
		
	}*/

	int p;
	rx = QRegExp("chars count=([\\d]+)");
	if((p = rx.indexIn(data)) != -1)
	{
		uint32 numGlyphs = rx.cap(1).toUInt();

		data = data.right(data.size() - p - rx.matchedLength());
		rx = QRegExp("char id=([\\d]+)[\\s]+x=([\\d]+)[\\s]+y=([\\d]+)[\\s]+width=([\\d]+)[\\s]+height=([\\d]+)[\\s]+xoffset=([-]?[\\d]+)[\\s]+yoffset=([-]?[\\d]+)[\\s]+xadvance=([\\d]+)[\\s]+page=([\\d]+)[\\s]+chnl=([\\d]+)");

		for(uint32 i = 0; i < numGlyphs; ++i)
		{
			if((p = rx.indexIn(data)) != -1)
			{
				uint32 id = rx.cap(1).toUInt();
				int2 pos = int2(rx.cap(2).toInt(), rx.cap(3).toInt());
				int2 size = int2(rx.cap(4).toInt(), rx.cap(5).toInt());
				int2 off = int2(rx.cap(6).toInt(), rx.cap(7).toInt());
				int adv = rx.cap(8).toInt();
				int chnl = rx.cap(9).toInt();
				m_glyphs.insert(id, CharGlyph(pos, size, id, off, adv, chnl));

				data = data.right(data.size() - rx.matchedLength());
			}
			else
			{
				BOOSTEXT_THROW(exception(format("Missing character information, %1% characters declared but only %2% characters found") % numGlyphs % (i+1)));
			}
		}
	}
	else
	{
		BOOSTEXT_THROW(exception("Missing character information, number of characters not given"));
	}

	rx = QRegExp("kernings count=([\\d]+)");
	if((p = rx.indexIn(data)) != -1)
	{
		uint32 numPairs = rx.cap(1).toUInt();
		data = data.right(data.size() - p - rx.matchedLength());

		rx = QRegExp("kerning first=([\\d]+)[\\s]+second=([\\d]+)[\\s]+amount=([-]?[\\d]+)[\\s]+");
		for(uint32 i = 0; i < numPairs; ++i)
		{
			if((p = rx.indexIn(data)) != -1)
			{
				m_kerningPairs << KerningPair(rx.cap(1).toUInt(), rx.cap(2).toUInt(), rx.cap(3).toUInt());
			}
			else
			{
				BOOSTEXT_THROW(exception(format("Missing kerning pairs: %1% pairs declared, but only %1% pairs given") % numPairs % (i+1)));
			}
		}
	}
	// Kerning pairs are optional
}
///////////////////////////////////////////////////////////////////////////////////////////////////

AdvancedFont::AdvancedFont(QDomElement elem, QDir path)
	: BasicFont(elem, path)
	, AdvancedGlyph(elem, path)
{
	if(!elem.hasAttribute("desc"))
		BOOSTEXT_THROW(exception("'desc' attribute missing in 'font' element"));
	m_fileName = elem.attribute("desc");
}
///////////////////////////////////////////////////////////////////////////////////////////////////




QString AdvancedFont::fileName() const
{
	return m_fileName;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

QString AdvancedFont::textureFileName() const
{
	return AdvancedGlyph::fileName();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

QString AdvancedFont::name() const
{
	return m_desc.name;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void AdvancedFont::setPos(int2 pos)
{
	m_delta += pos - m_pos;

	// All glyph coordinates are given relative to the style's upper left corner.
	// All we need to do is to calculate the relative position between the current
	// and new position and shift all glyphs by that delta.
	foreach(CharGlyph& glyph, m_glyphs)
	{
		glyph.move(m_delta);
	}

	m_pos = pos;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




QDomElement AdvancedFont::domElement(QDomDocument& document) const
{
	QDomElement element = BasicFont::domElement(document);
	AdvancedGlyph::setAttributes(element);
	element.setTagName("font");
	element.setAttribute("desc", m_fileName);
	return element;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




QString AdvancedFont::openFile(QString fileName)
{
	QFile file(fileName);
	if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
		BOOSTEXT_THROW(exception(format("Unable to open file '%1%'") % fileName));

	return file.readAll();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

QString AdvancedFont::textureFileName(QString content, QString fileName)
{
	QRegExp rx("file=\\\"([^\\\"]+)\\\"");
	if(rx.indexIn(content) == -1)
		BOOSTEXT_THROW(exception("Missing file tag"));

	QFileInfo info(fileName);
	QDir dir = info.absolutePath();
	return dir.absoluteFilePath(rx.cap(1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
